package com.cloud.prac.aop;

import cn.hutool.crypto.SecureUtil;
import com.cloud.prac.aop.annotation.RepeatSubmit;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.http.HttpServletRequest;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 防重复提交切面类
 *
 * @author 24373
 * @version 1.0
 * @date 2024-08-04 11:42
 */
@Component
@Slf4j
@Aspect
public class RepeatAspect {

    private static final Map<String, String> map = new ConcurrentHashMap<>(32);

    @Pointcut("@annotation(com.cloud.prac.aop.annotation.RepeatSubmit)")

    public void pt() {
    }

    @Before("pt()")
    public void repeat(JoinPoint joinPoint) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String requestParams = parseArgs(joinPoint.getArgs());
        /**
         * 唯一值
         * 有token：token + 请求参数
         * 无token：请求ip + 请求路径 + 请求参数
         */
        String submitKey = StringUtils.removeStart(request.getHeader("token"), "Bearer ");
        if (StringUtils.isEmpty(submitKey)) {
            submitKey = request.getRemoteHost() + "-" + request.getRequestURI();
        }
        submitKey = SecureUtil.md5(submitKey + ":" + requestParams);
        String cacheKey = "repeat_submit:" + submitKey;
        //    todo redis获取key判断 ；
        String value = map.get(cacheKey);
        if (value == null) {
            //   todo redis放入缓存值
            map.putIfAbsent(cacheKey, "");
        } else {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
            throw new RuntimeException(annotation.message());
        }
    }

    private String parseArgs(Object[] args) {
        return "/test";
    }


}
